#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include "sqlite3.h"

void check(int rc, char *msg) {
  if (rc != SQLITE_OK && rc != SQLITE_ROW && rc != SQLITE_DONE) {
    fprintf(stderr, "%s error: %s\n", msg, sqlite3_errstr(rc));
    exit(1);
  }
}

void *session2_thread(void *arg) {
  sqlite3 *db;
  sqlite3_stmt *stmt;
  int rc;

  sleep(1);  // 确保Session1已经插入但未提交

  rc = sqlite3_open("test.db", &db);
  check(rc, "session2 open");

  // 开事务
  rc = sqlite3_exec(db, "BEGIN;", NULL, NULL, NULL);
  check(rc, "session2 begin");

  // 查询
  rc = sqlite3_prepare_v2(db, "SELECT * FROM t1;", -1, &stmt, NULL);
  check(rc, "session2 prepare");

  printf("Session2 sees: ");
  while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) {
    printf("%s ", sqlite3_column_text(stmt, 0));
  }
  printf("\n");

  sqlite3_finalize(stmt);
  sqlite3_exec(db, "COMMIT;", NULL, NULL, NULL);
  sqlite3_close(db);

  return NULL;
}

int main() {
  sqlite3 *db;
  sqlite3_stmt *stmt;
  int rc;

  // Session1 打开数据库
  rc = sqlite3_open("test.db", &db);
  check(rc, "open");

  // 设置WAL模式
  rc = sqlite3_exec(db, "PRAGMA journal_mode=WAL;", NULL, NULL, NULL);
  check(rc, "set wal");

  sqlite3_wal_autocheckpoint(db, 0);

  // 创建表
  rc = sqlite3_exec(db, "CREATE TABLE t1(value TEXT);",
                    NULL, NULL, NULL);
  check(rc, "create table");

  // Session1 第一次事务
  rc = sqlite3_exec(db, "BEGIN; ", NULL,
                    NULL, NULL);
  // rc = sqlite3_exec(db, "INSERT INTO t1 VALUES('abc');", NULL,
  //                   NULL, NULL);
  rc = sqlite3_exec(db, "COMMIT;", NULL,
                    NULL, NULL);
  check(rc, "session1 first tx");

  sqlite3_close(db);
  return 0;

  // Session1 第二次事务（不提交）
  rc = sqlite3_exec(db, "BEGIN;", NULL, NULL, NULL);
  check(rc, "session1 begin2");

  rc = sqlite3_exec(db, "INSERT INTO t1 VALUES('def');", NULL, NULL, NULL);
  check(rc, "session1 insert def");

  // Session1 内部查询
  rc = sqlite3_prepare_v2(db, "SELECT * FROM t1;", -1, &stmt, NULL);
  check(rc, "session1 prepare");
  printf("Session1 sees: ");
  while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) {
    printf("%s ", sqlite3_column_text(stmt, 0));
  }
  printf("\n");
  sqlite3_finalize(stmt);

  // 启动Session2线程
  pthread_t t2;
  pthread_create(&t2, NULL, session2_thread, NULL);

  pthread_join(t2, NULL);

  // 提交事务
  rc = sqlite3_exec(db, "COMMIT;", NULL, NULL, NULL);
  check(rc, "session1 commit");

  sqlite3_close(db);
  return 0;
}
